
#ifndef RT_USE_OLD_CONN_WRAP

#ifndef __RT_CONN_RLB_TCP_H__
#define  __RT_CONN_RLB_TCP_H__

#include "RtConnBase.h"
#include "RtCnBase.h"
#include "RtConnRlbTcpSendBuffer.h"

class CRtConnRlbTcpClient;
class CRtConnRlbTcpServer;
typedef CConnConnectorT<CRtConnRlbTcpClient>		CRtConnRlbTcpConnector;
typedef CConnAcceptorT<CRtConnRlbTcpServer>			CRtConnRlbTcpAcceptor;
typedef CConnAcceptorSinkT<CRtConnRlbTcpServer>		CRtConnRlbTcpAcceptorSink;
typedef ServerListT<CRtConnRlbTcpServer>			CRtConnRlbTcpServerList;

class CRtConnRlbTcp : public CRtConnBase 
{
public:
	CRtConnRlbTcp(CRtConnectionManager::CType inConnType);
	virtual ~CRtConnRlbTcp();

public:
	virtual RtResult SendData(
		CRtMessageBlock& inData,
		BOOL inSendImmediately = TRUE,
		BOOL inDestroyData = FALSE,
		DataPriority inPriority = DP_MEDIUM, 
		BOOL inNeedAck = TRUE);
	virtual RtResult SetOption(DWORD inCommand, LPVOID inArg);
	virtual RtResult GetOption(DWORD inCommand, LPVOID outArg);
	virtual RtResult Disconnect(RtResult inReason) = 0;

	virtual void OnReceive(
		CRtMessageBlock &aData,
		IRtTransport *aTrptId,
		CRtTransportParameter *aPara = NULL);
	virtual void OnSend(
		IRtTransport *aTrptId,
		CRtTransportParameter *aPara = NULL);
	virtual void OnDisconnect(RtResult inReason, IRtTransport* inTransport) = 0;

	virtual void OnTimer(CRtTimerWrapper* inId) = 0;

	WORD GetChannelId() const { return m_channelId; }
	void NeedKeepAlive(BOOL bNeedKeepAlive) { }

protected:
	virtual void OnRecvConnReq() { RT_ASSERTE(FALSE); }
	virtual void OnRecvConnResp() { RT_ASSERTE(FALSE); }
	virtual void OnRecvDisconn() { RT_ASSERTE(FALSE); }
	virtual void OnRecvRtt(DWORD inTimestamp) { RT_ASSERTE(FALSE); }
	virtual void OnException(RtResult inReason) = 0;

protected:
	void Reset4Recv()
	{
		m_recvPduLen = 1;
		m_recvDataLen = 0;
#ifdef RLBTCP_ENABLE_SHORT_DATALEN
		m_gotDataLen = TRUE;
#endif
		m_recvPduType = 0;
	}

// 	RtResult BindNetworkThread(CRtOptParamBindThread& inParam);
	void OnRecvAck(SeqType inAck);
	void SendKeepAlive();
	void SendRtt(DWORD inTimestamp);
	void SendDisconn();
	void Close_i(RtResult inReason = RT_OK);
	void ReleaseRecvBuffer();

protected:
	typedef enum {
		CS_INIT = RT_CONN_STATUS_INIT,
		CS_UNCONNECTED,
		CS_CONNECTED,
		CS_RECONNECTING, /// for client only
		CS_RECONNECTED,  /// for client only 
		CS_HANDSHAKE_OK,
		CS_WAIT_RECONNECT, 
	} ConnStatus;

	CRtConnectionManager::CType m_connType;
	WORD m_channelId;
	SeqType m_ackFromPeer;
	DWORD m_ticket;
	CRtConnRlbTcpSendBuffer m_sendBuffer;
	CRtMessageBlock* m_recvBuffer;
	CRtTimerWrapper m_sendDelayTimer;

	DWORD m_recvPduLen;
	DWORD m_recvDataLen;
#ifdef RLBTCP_ENABLE_SHORT_DATALEN
	BOOL m_gotDataLen; /// If or not <m_recvDataLen> is real data length.
#endif
	BYTE m_recvPduType;

	SeqType m_ackToPeer;
	DWORD m_unackedDataLen;
	WORD m_keepAliveInterval;
	WORD m_continuousIdleTime;
	BOOL m_isDataReceived;
	BOOL m_isDataSent;
	BOOL m_needOnSend; /// If or not need to callback OnSend() onto upper layer.

	friend class CRtConnRlbTcpSendBuffer;
	friend class CRtEventRlbTcpOnBindThread;
	friend class CRtEventRlbTcpServerRetrieve;
};

class CRtConnRlbTcpClient: public CRtConnRlbTcp
{
public:
	CRtConnRlbTcpClient(CRtConnectionManager::CType inConnType);
	virtual ~CRtConnRlbTcpClient();

public:
	virtual RtResult Disconnect(RtResult inReason);
	virtual void OnDisconnect(RtResult inReason, IRtTransport* inTransport);
	virtual void OnConnectIndication(
		RtResult inResult,
		IRtTransport* inTransport,
		IRtAcceptorConnectorId* inRequestId);

public:
	void CancelHandShake();
	void SetConnConnector(CRtConnRlbTcpConnector* pConnConnector) { m_connConnector = pConnConnector; }
	void ScheduleConnectTimer(const CRtTimeValue& aTimeout) {}

protected:
	virtual void OnTimer(CRtTimerWrapper* inId);
	virtual void OnRecvConnResp();
	virtual void OnRecvDisconn();
	virtual void OnRecvRtt(DWORD inTimestamp);
	virtual void OnException(RtResult inReason);

	RtResult SendConnReq();
	void SetWaitReconnectStatus()
	{
		RT_ASSERTE(m_status!=CS_WAIT_RECONNECT);
		SetStatus(CS_WAIT_RECONNECT);
		m_reconnectTimer.Schedule(this, (time_t)3, 1);
	}

protected:
	CRtAutoPtr<CRtConnRlbTcpConnector> m_connConnector;
	CRtTimerWrapper m_reconnectTimer;
	DWORD m_lastRtt;
};

class CRtConnRlbTcpServer: public CRtConnRlbTcp
{
public:
	CRtConnRlbTcpServer(CRtConnectionManager::CType inConnType);
	virtual ~CRtConnRlbTcpServer();

public:
	virtual RtResult Disconnect(RtResult inReason);
	virtual void OnDisconnect(RtResult inReason, IRtTransport* inTransport);
	virtual void OnConnectIndication(
		RtResult inResult,
		IRtTransport* inTransport,
		IRtAcceptorConnectorId* inRequestId);

public:
	void SetConnAcceptor(CRtConnRlbTcpAcceptor* pConnAcceptor) { m_connAcceptor = pConnAcceptor; }

protected:
	virtual void OnTimer(CRtTimerWrapper* inId);
	virtual void OnRecvConnReq();
	virtual void OnRecvDisconn();
	virtual void OnRecvRtt(DWORD inTimestamp);
	virtual void OnException(RtResult inReason);

	RtResult SendConnResp(RtResult inResult);
	DWORD GenerateTicket();

	static RtResult Retrieve(CRtConnRlbTcpServer* inNewServer, CRtConnRlbTcpServer* inOldServer);

protected:
	CRtAutoPtr<CRtConnRlbTcpAcceptor> m_connAcceptor;

	friend class CRtConnRlbTcp;
};

#endif //!__RT_CONN_RLB_TCP_H__

#endif // !RT_USE_OLD_CONN_WRAP
